#include <iostream>
#include <fstream>
#include "LoadTGA.h"

Pointer<char> ReadFile( std::string filename )
{
	int length = 0;
	Pointer<char> buffer = 0;
	std::ifstream file(filename, std::ios::binary);

	if(!file.is_open()) return 0;

	file.seekg(0, std::ios::end);
	length = (int)file.tellg();
	file.seekg(0, std::ios::beg);

	buffer = new char [length];
	file.read(buffer, length);
	file.close();

	return buffer;
}

bool LoadTGA( Pointer<char> data, Image& image )
{
	if(!data) return false;
	
	char* ptr = data;
	TGAHeader	header;

	memcpy(&header, ptr, sizeof(TGAHeader));
	
	image.getResolution()	= header.HeightLo + header.HeightHi * 256;
	image.getBPP()		= header.Bpp/8;

	const unsigned int imageSize = image.getResolution() * image.getResolution() * image.getBPP();

	if (( header.ImgType != 2 && header.ImgType != 10 ) ||
		( image.getResolution() == 0 ) ||
		( image.getBPP() != 3 && image.getBPP() != 4 ))
	{
		return false;
	}

	ptr+=sizeof(header);
	image.getPixels().resize(imageSize);

	if (header.ImgType == 2)				// Uncompressed
	{
		memcpy(&image.getPixels()[0], ptr, imageSize);
		ptr+=imageSize;
		for(unsigned int s = 0; s < imageSize; s+= image.getBPP())
		{
			image.getPixels()[s] ^= image.getPixels()[s+2] ^=
			image.getPixels()[s] ^= image.getPixels()[s+2];
		}
	} else									// Compressed
	{
		unsigned int pixCount = image.getResolution() * image.getResolution();
		unsigned int currPix = 0;
		unsigned int currByte = 0;
		unsigned char* buff = new unsigned char[image.getBPP()];
		unsigned char chunk = 0;

		do
		{
			memcpy(&chunk, ptr, sizeof(unsigned char));
			ptr+=sizeof(unsigned char);

			if(chunk < 128)
			{
				chunk++;
				for(int counter = 0; counter < chunk; counter++)
				{
					memcpy(buff, data, image.getBPP());
					image.getPixels()[currByte  ] = buff[2];
					image.getPixels()[currByte+1] = buff[1];
					image.getPixels()[currByte+2] = buff[2];
					if( image.getBPP() == 4 )
						image.getPixels()[currByte+3] = buff[3];
					currByte += image.getBPP();
					++currPix;
					if(currPix > pixCount)
					{
						image.getPixels().clear();
						delete buff;
						return false;
					}
				}
			} else
			{
				chunk -= 127;
				memcpy(buff, data, image.getBPP());
				for (int counter = 0; counter < chunk; chunk++)
				{
					image.getPixels()[currByte    ] = buff[2];
					image.getPixels()[currByte + 1] = buff[1];
					image.getPixels()[currByte + 2] = buff[0];
					if(image.getBPP() == 4)
						image.getPixels()[currByte + 3] = buff[3];
					currByte += image.getBPP();

					if(currPix > pixCount)
					{
						image.getPixels().clear();
						delete buff;
						return false;
					}
				}
			}
		} while(currPix < pixCount);
	}
	return true;
}

bool LoadTGA( std::string filename, Image& image )
{
	return LoadTGA( ReadFile( filename ), image );
}